-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core] dry run should use dev inspect executor #20109
base: main
Are you sure you want to change the base?
[core] dry run should use dev inspect executor #20109
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
3 Skipped Deployments
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change itself makes sense, but we should be careful about making sure this change does what we think it does (i.e. nothing, hopefully). Could you flesh out the test plan with various scenarios? If we don't have them as unit tests already, then we should add them. I would want to check that the following cases behave identically before and after this change,
- Gas estimation (calls dry run with empty gas object refs).
- Dry-running a transaction that fails
- Dry-running a transaction that succeeds
- Dry-running an exotic transaction, like a publish or upgrade.
The reason to be careful is that most transactions that go through the network go through a dry-run call first (to do gas estimation) so we want to make sure we don't break that path, or people won't be able to run transactions anymore.
Also good to get some reviews from folks on the Move side for this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see a handful of tests on sui-core
I'll look at expanding these. Appreciate the feedback I've been comparing the two code paths (dry vs dev inspect) and the only notable difference I found so far was the return types but more tests will be good as well. |
the issue I have and would love to see discussed (thus the tagging I added) is that - as I remember - devinspect performs operations that we do not do in dryrun, for instance saving results per command. Also I am not clear how dev inspect is going to evolve in the face of transaction replay and the ability to get more insights in a transaction as opposed to normal execution. |
Also this PR would bring JSON-RPC in line with how GraphQL works. |
I think the performance concerns are interesting and worth digging into. Re: The reason to do this was to give us a way to expose richer errors during dry-run (for PTBs in particular), by building on top of |
transaction_digest, | ||
); | ||
let skip_all_checks = false; | ||
let (inner_temp_store, _, effects, _execution_error) = executor.dev_inspect_transaction( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you speak a bit more to the motivation here? This is potentially a really big regression for folks, since it will increase the space for transactions that will pass "dry run" but then fail at execution.
For example, someone could do something they feel is harmless, like construct some user defined struct
or enum
from CallArg::Pure
. Dev inspect will gladly let you do this, but dry run (and in turn normal execution), will give you an error. There is a very long list of this sort of differing behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot to refresh before making this comment and now see all the other comments above. Reading.
Could you explain more what "the option to skip checks" entails? |
My first reaction to this news is that we have done a very mean thing to our GraphQL users, but I would be interested in learning more (especially with this "the option to skip checks" thing I don't understand) |
In GraphQL, there's a single combined
There are some more details in the RPC 2.0 RFC: #13700, particularly this part. We did this because people were regularly confused by the difference between dev-inspect and dry-run, and this was made worse by the fact that there were configurations that didn't work, that we did not have great reasons for, like:
The commonality is that none of these transactions' effects are committed to the chain, so we ended up retaining the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should probably learn to shut up a bit more when I haven't looked at code that I wrote more than a year ago.
The skip_checks
flag seems to doing the right thing in AuthorityState::dev_inspect_transaction_block
, and so I trust y'all if you think this will do the exact same behavior as dry-run today. (even though skip_checks
is a bit lacking as a name, I've never really thought of Move's type system as a "check" 😝)
I was about to approve this but... it looks like we don't have any tests for the behavior of dry-run
in sui-adapter-transactional-tests
. We probably want to add them before landing this to make sure we don't break anything. I would probably test
- All sorts of Gas craziness
- Object owner checks
- arbitrary args via bytes
- reference return values
- entry taint checks (if you want to lose your mind)
- function visibility/entry check bypassing
- conservation checks
I wouldn't be surprised if some of these tests exist in the integration test land, but I would be surprised if it was this exhaustive.
Do such tests exist for Graph QL?
there appear to be a few related to graphql.
|
I don't think those tests are stressing the semantic difference between dry-run and dev-inspect though, which is my concern with the change in this PR. |
Yeah, I don't think we have tests that would expose exactly this kind of dry-run vs dev-inspect strangeness in GraphQL (Today it's a little tough to write GraphQL transactional tests that involve building transactions to execute through GraphQL's It would probably be better to have those tests closer to the authority codebase where those differences are maybe more apparent? (In GraphQL we are already living a post-dryRun world too). |
I was imagining having the tests in sui-adapter-transactional-tests, yeah. |
1eb3321
to
2ee5708
Compare
in existing
I added
I'm going to sift through My main questions now are: reference return values I think are pretty straight forward specifically checking for this I think:
while I do see the flag for conservation checks and understand what it does, how you are suppose to violate it in a test I'm not sure of. I figure you need to break a few things in core parts of the code before that check comes into play since that would mean you were able to write a tx that inflates sui right? Can't find any examples of this in the code. |
2ee5708
to
3f0e2db
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The newly added tests look good so far! Recording some other tests we talked about adding:
- A transaction that passes an object param as a Pure argument.
- A transaction that uses the above technique to break conservation (i.e. the object is a
Coin<SUI>
- The gas estimation flow (dry-running a transaction with an empty gas payment list should succeed and when we run the transaction for real with the gas budget set according to how much gas the dry-run reportedly used, that run succeeds).
for (address, object_id) in objects { | ||
let obj = Object::with_id_owner_for_testing(object_id, address); | ||
for (address, object_id, obj) in objects { | ||
let obj = obj.unwrap_or(Object::with_id_owner_for_testing(object_id, address)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use the lazy variant if the default case involves non-trivial computation.
let obj = obj.unwrap_or(Object::with_id_owner_for_testing(object_id, address)); | |
let obj = obj.unwrap_or_else(|| Object::with_id_owner_for_testing(object_id, address)); |
Description
Necessary for follow up work to improve PTB errors on dry run.
Test plan
How did you test the new or updated feature?
Release notes
Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.
For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates.